package flexconsoleparser;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

import com.adobe.flexbuilder.editors.mxml.IMXMLEditor;

/**
 * @author lizhiyu
 * 
 */
public class FlexFileHyperlink implements IHyperlink {

	private IFile fFile;

	private int fLineNumber;

	private int fColumnNumber;

	private String fEditorId;


	/**
	 * @param file
	 * @param editorId
	 * @param fileLineNumber
	 * @param fileColNumber
	 */
	public FlexFileHyperlink(IFile file, String editorId, int fileLineNumber,
		int fileColNumber) {
		fFile = file;
		fLineNumber = fileLineNumber;
		fColumnNumber = fileColNumber;
		fEditorId = editorId;
	}

	/*
	 * when link activated, open the link file, locate to the error line
	 * 
	 * @see org.eclipse.ui.console.IHyperlink#linkActivated()
	 */
	public void linkActivated() {
		IWorkbenchPage page = getActivePage();
		if (page != null) {
			IEditorInput editorInput = new FileEditorInput(fFile);
			String editorId = getEditorId();
			boolean activateEditor = false;
				
			try {
				IEditorPart editorPart = page.openEditor(editorInput, editorId, activateEditor);
				
				if (fLineNumber > 0) {
					revealErrorLine(editorPart);
				}
			} catch (PartInitException e) {
				ParserPlugin.log(e);
			}
		}
	}
	
	private ITextEditor getTextEditorFormPart(IEditorPart editorPart) {
		if (editorPart instanceof ITextEditor) {
			return (ITextEditor) editorPart;
		} else if (editorPart instanceof IMXMLEditor) {
			return ((IMXMLEditor)editorPart).getTextEditor();
		} else {
			return null;
		}
	}
	
	private void revealErrorLine(IEditorPart editorPart) {
		
		ITextEditor textEditor = getTextEditorFormPart(editorPart);
		
		if (textEditor != null) {
			int fileOffset = -1;
			int fileLength = 0;
			
			IDocumentProvider provider = textEditor.getDocumentProvider();
			IEditorInput editorInput = textEditor.getEditorInput();
			try {
				provider.connect(editorInput);
			} catch (CoreException e) {
				// unable to link
				ParserPlugin.log(e);
				return;
			}
			
			IDocument document = provider.getDocument(editorInput);
			try {
				IRegion region = document.getLineInformation(fLineNumber - 1);
				fileOffset = region.getOffset();
				fileLength = region.getLength();
			} catch (BadLocationException e) {
				// unable to link
				ParserPlugin.log(e);
			}
			provider.disconnect(editorInput);
	
			if (fileOffset >= 0 && fileLength >= 0) {
				if (fColumnNumber >= 0) {
					fileOffset += fColumnNumber - 1;
					fileLength -= fColumnNumber - 1;
				}
				textEditor.selectAndReveal(fileOffset, fileLength);
			}
		}		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.console.IHyperlink#linkEntered()
	 */
	public void linkEntered() {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.console.IHyperlink#linkExited()
	 */
	public void linkExited() {
	}

	public IFile getFile() {
		return fFile;
	}

	public int getColumNumber() {
		return fColumnNumber;
	}

	public int getLineNumber() {
		return fLineNumber;
	}

	/**
	 * get current active page
	 * @return
	 */
	private static IWorkbenchPage getActivePage() {
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		// the active window will be null when running in a console
		if (window != null) {
			IWorkbenchPage page = window.getActivePage();
			if (page != null) {
				return page;
			}
		}
		return null;
	}

	private String getEditorId() {
		if (fEditorId == null) {
			IWorkbench workbench = PlatformUI.getWorkbench();
			// If there is a registered editor for the file use it.
			IEditorDescriptor desc = workbench.getEditorRegistry().getDefaultEditor(
				fFile.getName(), getFileContentType());
			if (desc == null) {
				// default editor
				desc = workbench.getEditorRegistry().findEditor(
					IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
			}
			fEditorId = desc.getId();
		}
		return fEditorId;
	}

	private IContentType getFileContentType() {
		try {
			IContentDescription description = fFile.getContentDescription();
			if (description != null) {
				return description.getContentType();
			}
		} catch (CoreException e) {
		}
		return null;
	}

}
